React Native Swipe History Implementation Plan
Date: January 15, 2025
Objective: Implement comprehensive swipe history feature for React Native with table-like interface and swipe-to-action UX
📋 Current Backend Context Analysis
✅ Available Backend APIs
1. GET /api/swipes - Comprehensive Swipe History
- Full feature set available: pagination, filtering, search, sorting
- Advanced filters: date range, score range, genres, release year, liked/skipped status
- Sorting options: timestamp, title, score, release_year (asc/desc)
- Pagination: configurable page size (1-50), total count included
- Response format:
{
swipes: SwipeWithDetails[],
pagination: { page, limit, total, totalPages },
filters: SwipeFilters // Applied filters for reference
}
2. PUT /api/swipes/[id] - Update Swipe
- Editable fields:
liked,score,skipped - Validation: mutual exclusivity (can't be both liked and skipped)
- Score range: 0-10 with decimal support
- Ownership verification: only user's own swipes
3. DELETE /api/swipes/[id] - Delete Swipe
- Soft delete available: removes from user's history
- Ownership verification: secure deletion
- Cache invalidation: automatic React Query cache updates
✅ Rich Data Available (SwipeWithDetails)
interface SwipeWithDetails {
// Swipe metadata
id: string
user_id: string
tmdb_id: number
liked: boolean | null
score: number | null
skipped: boolean
timestamp: string
created_at: string
updated_at: string
// Movie details (fully populated)
title: string
overview: string | null
poster_url: string | null
backdrop_url: string | null
release_date: string | null
release_year: number | null
genres: Array<{ id: number; name: string }> | null
vote_average: number | null
vote_count: number | null
runtime: number | null
// Computed fields
swipe_status: "liked" | "skipped" | "disliked" | "unrated"
score_category: "high" | "medium" | "low" | "very_low" | "unrated"
}
🎯 React Native Implementation Plan
Phase 1: Core List Implementation
1.1 FlatList-Based Table Component
// components/SwipeHistoryList.tsx
interface SwipeHistoryListProps {
filter?: "liked" | "skipped" | "all"
searchQuery?: string
sortBy?: "timestamp" | "title" | "score" | "release_year"
sortOrder?: "asc" | "desc"
}
// Key features:
- FlatList with optimized rendering
- Pull-to-refresh support
- Infinite scroll pagination
- Loading skeletons
- Empty states with contextual messaging
1.2 Swipe History Row Component
// components/SwipeHistoryRow.tsx
- Movie poster (64x96px with fallback)
- Title + release year
- Status badge (Liked/Disliked/Skipped)
- Score display (stars + numeric)
- Timestamp (relative: "2 days ago")
- Swipe actions (hidden by default)
Phase 2: Swipe-to-Action UX
2.1 React Native Gesture Handler Integration
// Using react-native-gesture-handler for smooth gestures
- PanGestureHandler for horizontal swipe detection
- Animated.View for smooth motion feedback
- Haptic feedback on gesture start/complete
- Visual indicators during swipe (icons appear)
2.2 Swipe Actions Implementation
// LEFT SWIPE ONLY (iOS native pattern) reveals actions on the right side
// Actions: Edit | Delete | Quick Rate | Like Toggle | View Details
interface SwipeAction {
id: string
icon: IconName
label: string
color: string
backgroundColor: string
onPress: (swipe: SwipeWithDetails) => void
width: number
}
// Specific actions based on requirements:
- Edit (pencil icon) → Opens NativeSheet with EditSwipeForm
- Delete (trash icon) → Single destructive action (no confirmation)
- Quick Rate (star icon) → Toggle between score ranges
- Like Toggle (heart icon) → Toggle liked/disliked state
- View Details (eye icon) → Navigate to movie detail page
2.3 Gesture Animation System
// Smooth reveal animations
- translateX with spring animation
- Scale animation for revealed actions
- Opacity fade for row content during swipe
- Snap-back animation when gesture cancelled
- Completion animation when action triggered
Phase 3: Advanced Features
3.1 Search & Filter Integration
// components/SwipeHistoryFilters.tsx
- Search bar with debounced API calls
- Filter chips (Liked, Skipped, High Rated, etc.)
- Sort options (Recent, Title A-Z, Rating High-Low)
- Date range picker (This Week, This Month, Custom)
- Genre filter (multi-select)
- Quick filters (Recent Activity, Favorites)
3.2 Edit Modal
// modals/EditSwipeModal.tsx
- Movie poster + title display
- Toggle buttons: Liked / Disliked / Skipped
- Star rating component (1-10 scale)
- Save/Cancel with loading states
- Optimistic UI updates
- Error handling with retry
3.3 Delete Confirmation
// modals/DeleteSwipeModal.tsx
- Movie poster + title
- Clear warning message
- Confirm/Cancel buttons
- Loading state during deletion
- Success feedback
🛠 Technical Implementation Details
Data Management
React Query Integration
// hooks/useSwipeHistory.ts
const useSwipeHistory = (filters: SwipeFilters) => {
return useInfiniteQuery({
queryKey: ["swipes", "history", filters],
queryFn: ({ pageParam = 1 }) => fetchSwipeHistory({ ...filters, page: pageParam }),
getNextPageParam: (lastPage) =>
lastPage.pagination.page < lastPage.pagination.totalPages ? lastPage.pagination.page + 1 : undefined,
staleTime: 5 * 60 * 1000, // 5 minutes
placeholderData: keepPreviousData, // Smooth filter transitions
})
}
State Management
// stores/useSwipeHistoryStore.ts
interface SwipeHistoryStore {
filters: SwipeFilters
searchQuery: string
sortBy: SortOption
sortOrder: "asc" | "desc"
selectedTab: "liked" | "skipped" | "all"
// Actions
updateFilters: (filters: Partial<SwipeFilters>) => void
updateSearch: (query: string) => void
updateSort: (sortBy: SortOption, order: "asc" | "desc") => void
resetFilters: () => void
}
Performance Optimizations
1. FlatList Optimizations
// Optimized FlatList configuration
- getItemLayout for consistent row heights
- keyExtractor using swipe.id
- removeClippedSubviews for large lists
- initialNumToRender: 10
- maxToRenderPerBatch: 5
- windowSize: 10
- updateCellsBatchingPeriod: 50
2. Image Loading
// Optimized poster loading
- react-native-fast-image for caching
- Placeholder components during load
- Error fallbacks with movie icon
- Appropriate resize modes
3. Gesture Performance
// Smooth gesture handling
- useNativeDriver: true for animations
- Worklet functions for gesture callbacks
- Minimal re-renders during gestures
- Debounced action triggers
🎨 UX/UI Design Specifications
Visual Design
1. Row Layout
[Poster] [Title + Year + Status] [Score] [Timestamp] [→]
64x96 [Flexible width ] [Fixed] [Fixed ] [16]
2. Swipe Reveal Design
// Left swipe (destructive/edit actions)
Row content slides right, revealing:
[🗑️ Delete] [✏️ Edit] behind the row
// Right swipe (quick actions)
Row content slides left, revealing:
[⭐ Rate] [👁️ View] behind the row
3. Color Scheme
const swipeColors = {
liked: "#22c55e", // Green
disliked: "#ef4444", // Red
skipped: "#6b7280", // Gray
editAction: "#3b82f6", // Blue
deleteAction: "#ef4444", // Red
background: theme.background,
surface: theme.surface,
}
3. Animation & Gesture Patterns
// Using react-native-reanimated (already in use for AnimatedSwipeCard)
- PanGestureHandler for horizontal LEFT swipe detection only
- Native iOS-style reveal animation with spring physics
- Haptic feedback on action execution + success logging
- Visual feedback during swipe (action icons appear progressively)
4. Component Library & Design System
// Following existing patterns:
- Use NativeSheet for edit modal (like UsernameEditSheet/ReorderSheet)
- Button variants: will create new cell action button variant
- Colors: Use existing theme colors (destructive, primary, muted, etc.)
- Success feedback: Haptic + console logging (future toast integration)
5. Swipe Action Specifications
// RIGHT-SIDE REVEAL (iOS native pattern):
const SWIPE_ACTIONS = [
{ id: "edit", icon: "pencil", color: "primary", width: 80 },
{ id: "delete", icon: "trash", color: "destructive", width: 80 },
{ id: "rate", icon: "star", color: "amber", width: 80 },
{ id: "like", icon: "heart", color: "liked/disliked", width: 80 },
{ id: "details", icon: "eye", color: "muted", width: 80 }
]
// Actions behavior:
- Edit → NativeSheet with form (like EditSwipeDialog pattern)
- Delete → Immediate deletion with haptic + log
- Rate → Cycle through score ranges (1-3, 4-6, 7-8, 9-10)
- Like → Toggle liked(true) ↔ disliked(false) ↔ neutral(null)
- Details → Navigate to movie detail page
📱 Component Architecture
File Structure
app/swipe/
├── swipehistory.tsx # Main screen
├── components/
│ ├── SwipeHistoryList.tsx # Main list component
│ ├── SwipeHistoryRow.tsx # Individual row
│ ├── SwipeHistoryFilters.tsx # Filter controls
│ ├── SwipeHistoryActions.tsx # Swipe action buttons
│ └── SwipeHistoryEmpty.tsx # Empty states
├── modals/
│ ├── EditSwipeModal.tsx # Edit swipe modal
│ ├── DeleteSwipeModal.tsx # Delete confirmation
│ └── SwipeDetailModal.tsx # Full movie details
├── hooks/
│ ├── useSwipeHistory.ts # Data fetching
│ ├── useSwipeActions.ts # CRUD operations
│ └── useSwipeGestures.ts # Gesture handling
└── stores/
└── useSwipeHistoryStore.ts # Filter/sort state
Component Props Interface
// Main screen props
interface SwipeHistoryScreenProps {
initialFilter?: "liked" | "skipped" | "all"
}
// List component props
interface SwipeHistoryListProps {
data: InfiniteData<SwipeHistoryResponse>
onRefresh: () => void
onLoadMore: () => void
onSwipeAction: (action: SwipeAction, swipe: SwipeWithDetails) => void
isLoading: boolean
isRefreshing: boolean
}
// Row component props
interface SwipeHistoryRowProps {
swipe: SwipeWithDetails
onSwipeStart: () => void
onSwipeComplete: (action: SwipeAction) => void
onPress: () => void
}
🚀 Implementation Phases
Phase 1: Foundation (Week 1)
- Basic FlatList implementation
- Simple row component with movie data
- Basic API integration with pagination
- Loading and error states
- Pull-to-refresh functionality
Phase 2: Core Features (Week 2)
- Search and basic filtering
- Sort functionality
- Edit modal implementation
- Delete functionality with confirmation
- Optimistic UI updates
Phase 3: Advanced UX (Week 3)
- Swipe gesture implementation
- Action reveal animations
- Haptic feedback integration
- Advanced filtering (date, genre, score)
- Empty states and error handling
Phase 4: Polish & Optimization (Week 4)
- Performance optimizations
- Accessibility improvements
- Gesture refinements
- Animation polish
- Comprehensive testing
⚡ Feasibility Assessment
✅ Highly Feasible
- Backend API: Fully featured and ready
- Data richness: All required fields available
- React Native ecosystem: Excellent gesture libraries available
- Performance: FlatList + React Query = smooth experience
- Existing patterns: Can leverage web implementation patterns
🎯 Implementation Complexity: Medium
- Swipe gestures: Well-documented with react-native-gesture-handler
- Animation system: react-native-reanimated v3 provides excellent tools
- State management: React Query + Zustand (already in use)
- Testing: Jest + React Native Testing Library
🚧 Potential Challenges
- Gesture conflicts: Ensure swipe gestures don't interfere with navigation
- Performance at scale: Large lists need careful optimization
- Cross-platform consistency: Gesture behavior differs iOS/Android
- Accessibility: Swipe actions need alternative access methods
💡 Recommended Improvements
Backend Enhancements (Optional)
// Add to existing API - batch operations
POST /api/swipes/batch
{
"operations": [
{ "id": "uuid1", "action": "delete" },
{ "id": "uuid2", "action": "update", "data": { "score": 8 } }
]
}
Performance Enhancements
// Implement virtual scrolling for massive lists
import { VirtualizedList } from "react-native"
// Add image prefetching for smooth scrolling
import FastImage from "react-native-fast-image"
Analytics Integration
// Track user interactions for UX insights
- Swipe gesture usage vs button taps
- Most common filter combinations
- Edit vs delete action frequency
- Search query patterns
📋 Next Steps
Immediate Actions
- Create base SwipeHistoryScreen component
- Implement basic FlatList with API integration
- Add search and filter controls
- Create edit/delete modals
Dependencies to Install
# Gesture handling
npm install react-native-gesture-handler react-native-reanimated
# Image handling
npm install react-native-fast-image
# Haptic feedback
npm install react-native-haptic-feedback
# Date handling (for filters)
npm install date-fns
Testing Strategy
// Unit tests
- Gesture calculations
- Filter logic
- API integration
- State management
// Integration tests
- Complete user flows
- Error scenarios
- Performance benchmarks
- Accessibility compliance
🎉 Expected User Experience
Core User Journey
- Enter swipe history → See clean list of all swipes
- Search for movie → Instant filtered results
- Swipe row left → Reveal edit/delete actions smoothly
- Tap edit → Modal opens with current settings
- Update rating → Optimistic UI update, smooth save
- Pull to refresh → Latest swipes appear with animation
Success Metrics
- Performance: 60fps scrolling, under 100ms gesture response
- Usability: under 2 taps to complete any action
- Discoverability: Swipe actions obvious within first use
- Reliability: Offline capability, robust error recovery
This plan leverages the robust backend infrastructure already in place and follows React Native best practices for a smooth, performant user experience.